#![allow(non_snake_case)]
use crate::{EditColValues, EditControl, TableState};
use leptos::prelude::*;
use serde_json::Value;
use shq_common::prelude::{
    edit_props::EditProps, format_json_value_with_space, table_props::TableProps, Align,
    ContextMenus, DataType,
};
#[component]
pub(super) fn TableBodyCell(
    col_name: String,
    dt: DataType,
    lp: Option<TableProps>,
    value: Value,
    value_label: Option<String>,
    row_index: usize,
    col_index: usize,
    cell_border: bool,
    col_span: Option<u8>,
    left_width: u16,
    can_update: bool,
    align: Option<Align>,
    is_select_cell: bool,
    context_menus: Option<StoredValue<ContextMenus>>,
    table_state: ReadSignal<TableState>,
) -> impl IntoView {
    let curr_cell = table_state.with_untracked(|ts| ts.curr_cell());
    let edit_col_vals = use_context::<ReadSignal<EditColValues>>();
    let can_list_edit = lp.as_ref().map_or(false, |lp| lp.edit);
    let mut edit_val: RwSignal<Option<Value>> = RwSignal::new(None);
    let mut edit_val_label: RwSignal<Option<String>> = RwSignal::new(None);
    let mut edit_props: StoredValue<Option<EditProps>> = StoredValue::new(None);
    let mut err_msg: RwSignal<Option<String>> = RwSignal::new(None);
    if let Some(edit_col_vals) = edit_col_vals.as_ref() {
        edit_col_vals.with_untracked(|ecv| {
            if let Some((idx, ep)) = ecv.get_edit_col(&col_name) {
                edit_val = ecv.get_value(row_index, idx);
                edit_val_label = ecv.get_title(row_index, idx);
                edit_props = StoredValue::new(Some(ep.clone()));
                err_msg = ecv.get_err_msg(row_index, idx);
            }
        })
    }
    let col_name = StoredValue::new(col_name);
    let ellipsis = lp.as_ref().map(|p| p.ellipsis).unwrap_or(false);
    let align = if let Some(align) = align {
        align
    } else {
        lp.as_ref().map(|p| p.align.clone()).unwrap_or(Align::Left)
    };
    let is_fixed = lp.as_ref().map(|p| p.fixed).unwrap_or(false);
    let value = StoredValue::new(value);
    let memo_val = Memo::new(move |_| {
        if let Some(v) = edit_val.get() {
            v
        } else {
            value.get_value()
        }
    });
    let memo_val_label = Memo::new(move |_| {
        if let Some(v) = edit_val_label.get() {
            Some(v)
        } else {
            value_label.clone()
        }
    });
    let fmt_val = Memo::new(move |_| {
        let fmt = lp.as_ref().map(|p| p.format.as_deref()).unwrap_or(None);
        if let Some(v) = edit_val_label.get() {
            (v, 0)
        } else {
            let v = value.get_value();
            format_json_value_with_space(Some(&dt), fmt, &v)
        }
    });
    let cell_content = move || {
        let (val, count) = fmt_val.get();
        let err_msg = err_msg.get();
        let has_err = err_msg.is_some() && !err_msg.as_ref().unwrap().is_empty();
        let content = if ellipsis {
            view! {
                <p class="text-nowrap text-ellipsis overflow-hidden" class=("text-red-600",has_err) class=("cursor-pointer",is_select_cell)
                   style:padding-left=format!("{}px", count*4)>
                    {val}
                </p>
            }
            .into_any()
        } else {
            view! {
                <p  class=("text-right",align==Align::Right)
                    class=("text-center",align==Align::Center)
                    class=("text-red-600",has_err)
                    class=("cursor-pointer",is_select_cell)
                    style:padding-left=format!("{}px", count*4)
                >{val}</p>
            }
            .into_any()
        };
        if let Some(err_msg) = err_msg {
            view! {
                <div class="tooltip tooltip-error z-30" data-tip={err_msg.clone()}>
                    {content}
                </div>
            }
            .into_any()
        } else {
            content
        }
    };
    let is_curr_cell = move || {
        curr_cell.with(|cc| {
            cc.as_ref()
                .map_or(false, |(ri, cj)| *ri == row_index && *cj == col_index)
        })
    };
    let can_edit = move || {
        can_update && can_list_edit && is_curr_cell() && edit_props.with_value(|v| v.is_some())
    };
    view! {
        <Show when=move||!can_edit()
            fallback=move || view! {
                <td class="border border-bg-300 bg-sky-50 relative" class=("hover",is_select_cell) colspan=col_span>
                    <EditControl
                        col_name
                        value=memo_val.get()
                        value_label=memo_val_label.get()
                        data_type=dt
                        edit_props=StoredValue::new(edit_props.get_value().unwrap())
                        border=false
                        is_init_focus=true
                    />
                </td>
            }
        >
            <Show when=move||!is_fixed fallback=move || view! {
                <th class="sticky z-10 bg-teal-50 shadow-r-lg relative" class=("border",cell_border) class=("border-bg-300",cell_border)
                    style:left=move || format!("{}px", left_width) colspan=col_span>
                    {cell_content}
                </th>
            }>
                <td class="relative" class=("border",move||cell_border) class=("border-bg-300",cell_border) class=("bg-sky-50",can_list_edit&&can_update)
                    class=("bg-teal-50",move||is_select_cell&&is_curr_cell()) colspan=col_span
                    on:click=move |e| {
                        e.prevent_default();
                        // e.stop_propagation();
                        if is_curr_cell() {
                            return;
                        }
                        let act_idx = table_state.with_untracked(|ts|ts.context_action_index());
                        if is_select_cell {
                            curr_cell.set(Some((row_index, col_index)));
                            if let Some(idx) = act_idx.get_untracked() {
                                let col_name = col_name.get_value();
                                let has_idx = context_menus.map(|cms| cms.with_value(|cms| cms.has_menu_index(&col_name, dt, idx))).unwrap_or(false);
                                if !has_idx {
                                    let default_idx = context_menus.map(|cms| cms.with_value(|cms| cms.get_default_action_index(&col_name, dt))).flatten();
                                    if let Some(didx) = default_idx {
                                        act_idx.set(Some(didx));
                                    }
                                    act_idx.set(None);
                                }
                            }
                        }else{
                            table_state.with_untracked(|ts| {
                                if ts.selected_indexs().with_untracked(|s| s == &[row_index]) {
                                    return; // 如果当前选中行就是点击的行，则不需要更新
                                }
                                ts.selected_indexs.set(vec![row_index]);
                                if let Some(cms) = context_menus {
                                    cms.with_value(|cms| {
                                        if let Some(idx) = cms.get_row_context_menu() {
                                            if act_idx.get_untracked().is_none() {
                                                act_idx.set(Some(idx));
                                            }
                                        }
                                    });
                                };
                            });
                        }
                    }
                    on:dblclick=move |e| {
                        e.prevent_default();
                        e.stop_propagation();
                        let col_name = col_name.get_value();
                        let act_id = context_menus.map(|cms| cms.with_value(|cms| cms.get_default_action_index(&col_name, dt))).unwrap_or(None);
                        if let Some(act_id) = act_id {
                            table_state.with_untracked(|ts|ts.context_action_index.set(Some(act_id)));
                        }
                    }
                    on:contextmenu=move |e| {
                        e.prevent_default();
                        // e.stop_propagation();
                        let x = e.client_x();
                        let y = e.client_y();
                        table_state.with_untracked(|ts| {
                            if !is_curr_cell() {
                                curr_cell.set(Some((row_index, col_index)));
                            }
                            let col_name = col_name.get_value();
                            let act_idx = ts.context_action_index();
                            if let Some(idx) = act_idx.get_untracked() {
                                let has_idx = context_menus.map(|cms| cms.with_value(|cms| cms.has_menu_index(&col_name, dt, idx))).unwrap_or(false);
                                if !has_idx {
                                    act_idx.set(None);
                                }
                            }
                            let has_menus = context_menus.map(|cms| cms.with_value(|cms| cms.get_context_menu_count(&col_name, dt)) > 0).unwrap_or(false);
                            if has_menus {
                                ts.curr_context_menu.set(Some((x, y, col_name, dt)));
                            }
                        });
                    }
                >
                    {cell_content}
                </td>
            </Show>
        </Show>
    }
}
